home *** CD-ROM | disk | FTP | other *** search
- ;-------------------------------------------------------------------------
- ; MERLIN.ASM
- ;
- ; 1/15/90
- ;
- ; David Stafford
- ; CIS 72411,2670 or 76666,2542
- ;
- ; This is heavily hacked code. Don't take it too seriously.
- ;
- ; See MERLIN.DOC for usage instructions.
- ; Assembled with Turbo Assembler.
- ;-------------------------------------------------------------------------
-
- locals
- code segment para public 'code'
- assume cs:code,ds:code,es:code,ss:code
- org 100h
-
- ;-------------------------------------------------------------------------
- ;Store the board at PSP:80h (command line)
- ;-------------------------------------------------------------------------
-
- Board equ 80h
-
- ;-------------------------------------------------------------------------
- ;Window details
- ;-------------------------------------------------------------------------
-
- COrgX equ 1 ;client X origin
- COrgY equ 1 ;client Y origin
- PaneWidth equ 6 ;window pane width
- PaneHeight equ 3 ;window pane height
- CWidth equ PaneWidth*3+2 ;client window width
- CHeight equ PaneHeight*3+2 ;client window height
- FOrgX equ COrgX-1 ;frame X origin
- FOrgY equ COrgY-1 ;frame Y origin
- FWidth equ CWidth+2 ;frame window width
- FHeight equ CHeight+2 ;frame window height
-
- ;-------------------------------------------------------------------------
- ;.COM entry point
- ;
- ;Ordinarily I put these things at the end of the program (so they don't
- ;hang around resident) but this one is small.
- ;-------------------------------------------------------------------------
-
- Init proc near
- call Scramble
-
- mov ax,3509h ;get interrupt vector 9
- int 21h ;(keyboard interrupt)
- mov word ptr OldInt9,bx
- mov word ptr OldInt9+2,es
-
- mov ax,2509h ;set interrupt vector 9
- mov dx,offset TSRMain
- int 21h
-
- mov dx,offset ResidentEnd
- int 27h ;terminate and stay resident
- endp
-
- ;-------------------------------------------------------------------------
- ;Draws the bars in the box frame.
- ;
- ;Calls DrawLine (in a manner of speaking) twice and falls through.
- ;-------------------------------------------------------------------------
-
- DrawBars proc near
- mov bx,0b3b3h
- mov dl,0b3h
- mov ax,offset DrawLine ;execute DrawLine 3 times
- push ax
- push ax
- endp ;fall through
-
- ;-------------------------------------------------------------------------
- ;Draws a single line.
- ;
- ;in: bl = left char, bh = right char, dl = intersection char
- ; es:di points into video
- ;-------------------------------------------------------------------------
-
- DrawLine proc near
- mov ah,0fh ;color attribute
- mov al,bl
- stosw
- mov cl,CWidth
- mov al,0c4h ;horizontal single line
- rep
- stosw
- mov es:[di-(PaneWidth+1)*2],dl
- mov es:[di-(PaneWidth+1)*4],dl
- mov al,bh
- stosw
- add di,160-FWidth*2 ;point to next line in video
- ret
- endp
-
- ;-------------------------------------------------------------------------
- ;Int 9 (keyboard interrupt) entry point
- ;This routine is modified by Accept, Restore and Init so be careful!
- ;-------------------------------------------------------------------------
-
- TSRMain proc near
- sti
- push ax
- in al,60h ;get scan code from keyboard
- cmp al,50 ;check for 'm' key
- jne @@Exit ;no, then exit
- mov ah,2 ;check shift keys
- int 16h
- and al,0fh
- cmp al,4 ;check CTRL key
- je Accept ;OK, popup
- @@Exit: pop ax
- cli
- @@ByeByte: db 0eah ;intersegment far jump
- OldInt9 dd ? ;chain to previous int 9 handler
- endp
-
- ;-----------------------------------------------------------------------------
- ;Gets here when the hotkey has been accepted.
- ;Modifies TSRMain.
- ;-----------------------------------------------------------------------------
-
- Accept proc near
- cld
-
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push es
-
- push cs ;ds = cs
- pop ds
- push cs ;es = cs
- pop es
-
- ;Here I install a short jmp to @@ByeBye in TSRMain
- mov word ptr TSRMain,12ebh
- endp ;fall through
-
- ;-----------------------------------------------------------------------------
- ;Resets the keyboard and signals end-of-interrupt to the 8259
- ;-----------------------------------------------------------------------------
-
- ResetKeyboard proc near
- in al,61h ;get current control port value
- push ax ;save it
- or al,80h ;set bit 7
- out 61h,al ;send reset value
- pop ax ;restore control port value
- out 61h,al ;enable keyboard
- cli
- mov ax,0f20h ;al = get EOI value
- ;ah = get video mode (below)
- out 20h,al ;send EOI to 8259
- sti
- endp ;fall through
-
- ;-----------------------------------------------------------------------------
- ;Gets the video mode and saves the video buffers
- ;
- ;The strange looking segment address (0b03fh) for the video screen lets
- ;me assume an offset of zero for some accesses (saves a couple bytes).
- ;-----------------------------------------------------------------------------
-
- GetVideo proc near
- int 10h ;get the video mode (assume ah = 0fh)
- ;bh = video page
- mov dx,0b03fh ;assume mono
- cmp al,7 ;is it mono?
- je @@GotSegment
- cmp al,2 ;color?
- je @@GetPage
- cmp al,3 ;color?
- jne BadVideo ;bad video mode, don't pop up!
-
- @@GetPage: mov dh,0b8h ;set for color
- add dh,bh ;add the page
-
- @@GotSegment: mov ds,dx ;get video segment
-
- mov ah,3 ;bh = video page
- int 10h ;get cursor shape & position
- push cx ;save cursor shape
-
- mov ch,20h
- mov ah,1 ;hide cursor
- int 10h ;set cursor shape
-
- xor si,si ;offset into video screen
- mov di,offset VideoBuf
- mov bx,FHeight ;bx = loop variable
-
- @@NextLine: mov cx,FWidth
- rep
- movsw
-
- add si,160-FWidth*2 ;point to next line in video
- dec bx
- jnz @@NextLine
-
- push ds ;es = ds (video page)
- pop es
- push cs ;ds = cs
- pop ds
- endp ;fall through
-
- ;-----------------------------------------------------------------------------
- ;Draws the box frame
- ;-----------------------------------------------------------------------------
-
- DrawFrame proc near
- xor di,di ;offset into video screen
-
- mov bx,0bfdah
- mov dx,03c2h ;dh is loop counter
- jmp short @@Doit
-
- @@Top: mov bx,0b4c3h
- mov dl,0c5h
-
- @@DoIt: call DrawLine
- call DrawBars
-
- dec dh
- jnz @@Top
-
- mov bx,0d9c0h
- mov dl,0c1h
- call DrawLine
- jmp short DrawClient
- endp
-
- ;-------------------------------------------------------------------------
- ;Restores the video buffer
- ;Modifies TSRMain.
- ;-------------------------------------------------------------------------
-
- Restore proc near
- xor di,di ;offset into video screen
- mov si,offset VideoBuf
- mov bl,FHeight ;bx = counter, assume bh = 0
- @@NextLine:
- mov cl,FWidth ;assume ch = 0
- rep
- movsw
- add di,160-FWidth*2 ;point to next line in video
- dec bx
- jnz @@NextLine
-
- mov ah,1
- pop cx ;restore cursor shape
- int 10h
-
- ;Arrive here if in graphics mode.
- ;Uninstall the short jmp to @@ByeBye in TSRMain.
- BadVideo: mov word ptr TSRMain,050fbh
-
- pop es ;exit
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- iret
- endp
-
- ;-------------------------------------------------------------------------
- ;Scrambles the game board
- ;-------------------------------------------------------------------------
-
- Scramble proc near
- push ds
- mov ds,dx ;assume dx = 0
- mov ax,ds:[46ch] ;get timer (random number)
- pop ds
-
- mov bl,Board+1 ;assume bh = 0
- mov cl,9 ;loop counter (assume ch = 0)
-
- @@Top: xor dl,dl
- shr ax,1
- adc dl,dl
- mov [bx],dl
- inc bx
- loop @@Top
- ret
- endp
-
- ;-------------------------------------------------------------------------
- ;Jump here when you want to scramble the board and return to DrawClient
- ;-------------------------------------------------------------------------
-
- ScrambleKey proc near
- call Scramble
- endp ;fall through
-
- ;-----------------------------------------------------------------------------
- ;Draws the individual squares
- ;-----------------------------------------------------------------------------
-
- DrawClient proc near
- mov dx,Board+1 ;damn, can't assume dh = 0
- mov di,(CHeight*80+COrgX)*2 ;offset into video screen
-
- mov cl,3
- @@Top: push cx
- mov bl,3
- @@Top1: mov si,dx
- mov bh,3
- @@Top2: mov ax,7020h ;char/attribute
- mov cl,[si]
- jcxz @@0 ;assume ch = 0
- cbw ;ah = 0
- @@0: mov cl,6
- rep
- stosw
- inc si ;next square
- inc di ;skip video column
- inc di
- dec bh
- jnz @@Top2
- sub di,160+CWidth*2+2 ;move up a row
- dec bx ;assume bh = 0
- jnz @@Top1
- sub di,160
- mov dx,si
-
- pop cx
- loop @@Top
- endp ;fall through
-
- ;-----------------------------------------------------------------------------
- ;Gets a keypress and performs the desired action
- ;-----------------------------------------------------------------------------
-
- GetKey proc near
- cbw ;assume al < 128
- cwd ;dx = 0
- int 16h ;get keypress
- cmp al,27 ;escape?
- je Restore
- cmp al,13
- je ScrambleKey
-
- sub al,'0'
- cmp al,9
- ja GetKey
-
- mov dl,al
- mov bx,offset Keys-1
- xlat
- mov bx,Board+1
- mov cl,9
-
- @@ToggleLoop: dec dx ;assume dh = 0
- jz @@Toggle
- shr al,1
- jnc @@Bottom
- @@Toggle: xor byte ptr [bx],1
- @@Bottom: inc bx
- loop @@ToggleLoop
- jmp short DrawClient
- endp
-
- ;-------------------------------------------------------------------------
- ;Data
- ;-------------------------------------------------------------------------
-
- ;Bitmaps for which keys affect which squares. Only 8 bits for each
- ;square because we assume key X toggles square X. Otherwise we would
- ;have to use 9 more bytes for this table and the added logic is less
- ;than 9 bytes.
-
- Keys db 00001101b ;1
- db 00000011b ;2
- db 00011010b ;3
- db 00100001b ;4
- db 01011010b ;5
- db 10000100b ;6
- db 01011000b ;7
- db 11000000b ;8
- db 10110000b ;9
-
- ;Video save area
-
- VideoBuf label byte ;screen save area
- ResidentEnd equ offset VideoBuf + FWidth * FHeight * 2
-
- ends
- end Init